package aplicacion.votaciones;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
import edu.uptc.votaciones.conf.HibernateUtil;
import edu.uptc.votaciones.entity.Departamento;
import edu.uptc.votaciones.entity.Formula;
import edu.uptc.votaciones.entity.Persona;
import edu.uptc.votaciones.entity.Voto;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import javax.swing.JOptionPane;
import org.hibernate.Query;
import org.hibernate.Session;

/**
 *
 * @author Syslink
 */
public class AplicacionVotaciones {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        String opcionesMenu = "Seleccione una opción:\n1. Ingresar Departamentos\n2. Ingresar Personas\n3. Ingresar Candidatos\n4. Votar\n5.Ver resultados\n6. Salir";
        int opcion = 0;
        String opcionSeleccionada;
        AplicacionVotaciones p = new AplicacionVotaciones();
        boolean continuar = true;
        do {
            try {
                opcionSeleccionada = JOptionPane.showInputDialog(null, opcionesMenu, "Bienvenido", JOptionPane.INFORMATION_MESSAGE);
                if (null == opcionSeleccionada) {
                    break;
                } else {
                    opcion = Integer.parseInt(opcionSeleccionada);
                    if (opcion == 1) {
                        p.ingresarDepartamentos();
                    } else if (opcion == 2) {
                        p.ingresarPersonas();
                    } else if (opcion == 3) {
                        p.ingresarFormulas();
                    } else if (opcion == 4) {
                        p.votar();
                    } else if (opcion == 5) {
                        p.verResultados();
                    } else if (opcion == 6) {
                        continuar = false;
                    } else {
                        throw new Exception("Debe ingresar una opción válida");
                    }
                }
            } catch (NumberFormatException e) {
                JOptionPane.showMessageDialog(null, "Ingrese un número valido", "Error", JOptionPane.ERROR_MESSAGE);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            }
        } while (continuar);

        //p.ingresarDepartamentos();
        // p.insertarPersonas();
        //p.insertarCandidatos();
        // p.ingresarPersonas();
    }

    public void ingresarDepartamentos() {
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        List<Departamento> departamentos = sesion.createQuery("From Departamento").list();
        sesion.getTransaction().begin();
        if (departamentos.isEmpty()) {
            String[] depart = {"Amazonas", "Antioquia", "Arauca", "Atlántico", "Bolívar", "Boyacá", "Caldas", "Caquetá", "Casanare", "Cauca", "Cesar", "Chocó", "Córdoba", "Cundinamarca", "Distrito Capital", "Guainía", "Guaviare", "Huila", "La Guajira", "Magdalena", "Meta", "Nariño", "Norte de Santander", "Putumayo", "Quindío", "Risaralda", "San Andrés y Providencia", "Santander", "Sucre", "Tolima", "Valle del Cauca", "Vaupés", "Vichada"};
            for (String nombre : depart) {
                Departamento d = new Departamento(nombre);
                departamentos.add(d);
                sesion.save(d);
            }
        }
        boolean continuar = false;
        do {
            try {
                Departamento d = new Departamento();
                String nombre = this.getValorIngresadoDialogo("Nombre del departamento ");
                if (buscarDepartamentoPorNombre(departamentos, nombre)) {
                    throw new Exception("El departamento " + nombre + " ya existe");
                }
                sesion.save(d);
                sesion.getTransaction().commit();
                continuar = true;
                JOptionPane.showMessageDialog(null, "Se ingresaron los datos correctamente", "Exito", JOptionPane.INFORMATION_MESSAGE);
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            } finally {
                sesion.flush();
                sesion.close();
            }
        } while (!continuar);
    }

    public void ingresarFormulas() {
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        List<Persona> personas = sesion.createQuery("From Persona").list();
        try {
            if (personas.size() < 2) {
                throw new Exception("No hay suficientes personas registradas");
            }
            String[] personasRegistradas = new String[personas.size()];
            for (int i = 0; i < personas.size(); i++) {
                personasRegistradas[i] = personas.get(i).getDocumento() + ">" + personas.get(i).getNombres() + " " + personas.get(i).getNombres();
            }
            boolean continuar = false;
            sesion.getTransaction().begin();
            do {
                try {
                    Formula f = new Formula();
                    String presidente = (String) JOptionPane.showInputDialog(null, "Selecciona el presidente", "Seleccion departamento", JOptionPane.QUESTION_MESSAGE, null, personasRegistradas, personasRegistradas[0]);
                    if (null == presidente) {
                        break;
                    }
                    String[] datos = presidente.split(">");
                    int doc = Integer.parseInt(datos[0]);
                    f.setPresidente(this.getPersona(personas, doc));
                    String vicePresidente = (String) JOptionPane.showInputDialog(null, "Selecciona el vicepresidente", "Seleccion departamento", JOptionPane.QUESTION_MESSAGE, null, personasRegistradas, personasRegistradas[0]);
                    if (null == vicePresidente) {
                        break;
                    }
                    datos = vicePresidente.split(">");
                    doc = Integer.parseInt(datos[0]);
                    f.setVicepresidente(this.getPersona(personas, doc));
                    sesion.save(f);
                    sesion.getTransaction().commit();
                    continuar = true;
                    JOptionPane.showMessageDialog(null, "Se ingresaron los datos correctamente", "Exito", JOptionPane.INFORMATION_MESSAGE);
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(null, "Ingrese un número valido", "Error", JOptionPane.ERROR_MESSAGE);
                } finally {
                    sesion.flush();
                    sesion.close();
                }
            } while (!continuar);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }

    public void votar() {
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        List<Persona> personas = sesion.createQuery("From Persona").list();
        List<Departamento> departamentosExistents = sesion.createQuery("From Departamento").list();

        String[] personasRegistradas = new String[personas.size()];
        for (int i = 0; i < personas.size(); i++) {
            personasRegistradas[i] = personas.get(i).getDocumento() + ">" + personas.get(i).getNombres() + " " + personas.get(i).getNombres();
        }
        sesion.getTransaction().begin();
        List<Formula> formulas = sesion.createQuery("From Formula").list();
        try {
            if (formulas.isEmpty()) {
                throw new Exception("No hay suficientes personas registradas");
            }
            String[] formulasRegistradas = new String[formulas.size()];
            for (int i = 0; i < formulas.size(); i++) {
                formulasRegistradas[i] = formulas.get(i).getIdFormula() + ">" + formulas.get(i).getPresidente().getNombres() + "--" + formulas.get(i).getVicepresidente().getNombres();
            }
            String[] departamentos = new String[departamentosExistents.size() + 1];
            for (int i = 0; i < departamentosExistents.size(); i++) {
                departamentos[i] = departamentosExistents.get(i).getNombre();
            }
            boolean continuar = false;
            sesion.getTransaction().begin();
            do {
                try {

                    Voto v = new Voto();

                    String personaVota = (String) JOptionPane.showInputDialog(null, "Selecciona el presidente", "Seleccion departamento", JOptionPane.QUESTION_MESSAGE, null, formulasRegistradas, formulasRegistradas[0]);
                    if (null == personaVota) {
                        break;
                    }
                    String[] datosPersona = personaVota.split(">");
                    int documento = Integer.parseInt(datosPersona[0]);
                    v.setPersona(this.getPersona(personas, documento));

                    String de = (String) JOptionPane.showInputDialog(null, "Selecciona el departamento que desee", "Seleccion departamento", JOptionPane.QUESTION_MESSAGE, null, departamentos, departamentos[0]);

                    v.setDepartamento(this.getDepartamentoPorNombre(departamentosExistents, de));

                    String formulaVoto = (String) JOptionPane.showInputDialog(null, "Selecciona el presidente", "Seleccion departamento", JOptionPane.QUESTION_MESSAGE, null, formulasRegistradas, formulasRegistradas[0]);
                    if (null == formulaVoto) {
                        break;
                    }
                    String[] datos = formulaVoto.split(">");
                    int idVoto = Integer.parseInt(datos[0]);
                    v.setFormula(this.getFormulaPorID(formulas, idVoto));

                    sesion.save(v);
                    sesion.getTransaction().commit();
                    continuar = true;
                    JOptionPane.showMessageDialog(null, "Se ingresaron los datos correctamente", "Exito", JOptionPane.INFORMATION_MESSAGE);
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(null, "Ingrese un número valido", "Error", JOptionPane.ERROR_MESSAGE);
                }
            } while (!continuar);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        } finally {
            sesion.flush();
            sesion.close();
        }

    }

    public void ingresarPersonas() {
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        List<Departamento> departamentosExistents = sesion.createQuery("From Departamento").list();

        boolean continuar = false;
        sesion.getTransaction().begin();
        do {
            String[] departamentos = new String[departamentosExistents.size() + 1];
            for (int i = 0; i < departamentosExistents.size(); i++) {
                departamentos[i] = departamentosExistents.get(i).getNombre();
            }
            departamentos[departamentosExistents.size() - 1] = "Crear Nuevo";
            try {
                Persona p = new Persona();
                p.setDocumento(Integer.parseInt(this.getValorIngresadoDialogo("Documento Persona")));
                p.setNombres(this.getValorIngresadoDialogo("Nombre Persona"));
                p.setApellidos(this.getValorIngresadoDialogo("Apellido Persona"));
                Departamento d = new Departamento();
                String de = (String) JOptionPane.showInputDialog(null, "Selecciona el departamento que desee", "Seleccion departamento", JOptionPane.QUESTION_MESSAGE, null, departamentos, departamentos[0]);
                String nombre;
                if (de.equals("Crear Nuevo")) {
                    do {
                        nombre = this.getValorIngresadoDialogo("Nombre Departamento");
                        if (null == nombre) {
                            JOptionPane.showMessageDialog(null, "El nombre es obligatorio", "Error", JOptionPane.ERROR_MESSAGE);
                        } else {
                            d.setNombre(nombre);
                        }
                    } while (nombre == null);
                    departamentosExistents.add(d);
                } else {
                    d = this.getDepartamentoPorNombre(departamentosExistents, de);
                }
                p.setDepartamento(d);
                sesion.save(p);
                continuar = true;
            } catch (Exception e) {
                JOptionPane.showMessageDialog(null, "Ingrese un número valido", "Error", JOptionPane.ERROR_MESSAGE);
            } finally {
                sesion.flush();
                sesion.close();
            }
        } while (!continuar);
    }

    public boolean buscarDepartamentoPorNombre(List<Departamento> departamentos, String nombre) {
        return departamentos.stream().anyMatch((departamento) -> (departamento.getNombre().toLowerCase().equals(nombre.toLowerCase())));
    }

    public Departamento getDepartamentoPorNombre(List<Departamento> departamentos, String nombre) {
        Departamento departamento = null;
        for (Departamento depto : departamentos) {
            if (depto.getNombre().equals(nombre)) {
                departamento = depto;
                break;
            }
        }
        return departamento;
    }

    public Departamento getDepartamento(List<Departamento> departamentos, int idDepartamento) throws Exception {
        Departamento d = new Departamento();
        for (Departamento dep : departamentos) {
            if (dep.getIdDepartamento() == idDepartamento) {
                d = dep;
            }
            break;
        }
        return d;
    }

    public String getValorIngresadoDialogo(String titulo) {
        String cadena;
        do {
            cadena = JOptionPane.showInputDialog(null, "Ingreso de " + titulo, titulo, JOptionPane.INFORMATION_MESSAGE);
            if (null == cadena) {
                JOptionPane.showMessageDialog(null, "El " + titulo + " es obligatorio", "Error", JOptionPane.ERROR_MESSAGE);
            }
        } while (cadena == null);
        return cadena;
    }

    public Persona getPersona(List<Persona> personas, int documento) throws Exception {
        Persona p = new Persona();
        for (Persona persona : personas) {
            if (persona.getDocumento() == documento) {
                p = persona;
            }
            break;
        }
        return p;
    }

    public Formula getFormulaPorID(List<Formula> formulas, int idVoto) {
        Formula f = null;
        for (Formula formula : formulas) {
            if (f.getIdFormula() == idVoto) {
                f = formula;
                break;
            }
        }
        return f;
    }
    
    public void verResultados() {
        Session sesion = HibernateUtil.getSessionFactory().openSession();
        List<Voto> votos = sesion.createQuery("From Voto").list();
        List<Formula> formulas = sesion.createQuery("From Formula").list();
        List<Departamento> departamentos = sesion.createQuery("From Departamento").list();
        String[] formulasRegistradas = new String[formulas.size()];
            for (int i = 0; i < formulas.size(); i++) {
                formulasRegistradas[i] = formulas.get(i).getIdFormula() + ">" + formulas.get(i).getPresidente().getNombres() + "--" + formulas.get(i).getVicepresidente().getNombres();
            }
        try {
            if (votos.isEmpty()) {
                throw new Exception("No hay votos registrados");
            }
            boolean continuar = false;
            do {
                try {
                    Formula f = this.getGanador(formulas, votos);
                    Departamento d = this.getDepartamentoGanador(f, votos, departamentos);
                    continuar = true;
                    String mensaje = "El grupo ganador fue: "+f.getPresidente().getNombres()+" "+
                            f.getPresidente().getApellidos()+" - "+f.getVicepresidente().getNombres()+" "
                                    +f.getVicepresidente().getApellidos()+" y el departamento"
                                    +"que mas votó por este grupo fué: "+d.getNombre();
                    JOptionPane.showMessageDialog(null, mensaje, "Exito", JOptionPane.INFORMATION_MESSAGE);
                } catch (Exception e) {
                    JOptionPane.showMessageDialog(null, "Ingrese un número valido", "Error", JOptionPane.ERROR_MESSAGE);
                } finally {
                    sesion.flush();
                    sesion.close();
                }
            } while (!continuar);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
        }
    }
    
    public Formula getGanador(List<Formula> formulas, List<Voto> votos){
        Formula ganador = new Formula();
        int mayor=0;
        int contadorVotos=0;
        for(Formula f : formulas){
            contadorVotos=0;
            for(Voto voto : votos){
                if(voto.getFormula()==f){
                    contadorVotos++;
                }
            }
            if(contadorVotos>mayor){
                mayor = contadorVotos;
                ganador = f;
            }
        }
        return ganador;
    }
    
    public Departamento getDepartamentoGanador(Formula f, List<Voto> votos, List<Departamento>departamentos){
        Departamento deptoGanador = new Departamento();
        int mayor=0;
        List<Voto> grupo = new ArrayList<>();
        int contadorVotos=0;
            for(Voto voto : votos){
                if(voto.getFormula()==f){
                    grupo.add(voto);
                }
            }
            for(Departamento departamento: departamentos){
                for(Voto voto: grupo){
                    if(voto.getDepartamento()==departamento){
                        contadorVotos++;
                    }
                }
                if(contadorVotos>mayor){
                    mayor=contadorVotos;
                    deptoGanador = departamento;
                }
            }
        return deptoGanador;
    }
}
